#!/usr/bin/env python

__author__ = "Abhinav Sarkar"
__version__ = "0.1"
__license__ = "GNU Lesser General Public License"

class Tag (object):
	"""A class representing a tag.
	
	The Tag class exposes the following instance properties:
	
		tag.name
		tag.url
		tag.count
		tag.topAlbums
		tag.topAlbum
		tag.topArtists
		tag.topArtist
		tag.topTracks
		tag.topTrack
		
	The Tag class exposes the following instance methods:
	
		tag.AsDict()
		tag.GetTopAlbums()
		tag.GetTopArtists()
		tag.GetTopTracks()
	"""
	def __init__(self,
				 name = None,
				 url = None,
				 count = None):
		"""An object to hold a tag.
		
		This class is normally instantiated by the Webservice class.
		
		Args:
			name: name of this tag
			url: URL of this tag on last.fm
			count: count of this tag for a artist, album or track
			
		Usage:
			>>> import audioscrobblerws
			>>> ws = audioscrobblerws.Webservice()
			>>> tag = ws.GetTag('alternative')
		"""
		self.name = name
		self.url = url
		self.count = count

	def GetTopArtists(self):
		"""Get the top artists for this tag.

		Returns:
			An ordered list of Artist objects corresponding to this tags's top artists.

		Usage:
			>>> tag = ws.GetTag('alternative')
			>>> artists = tag.GetTopArtists()
			>>> [a.name for a in artists[:10]]
			['Radiohead', 'Muse', 'Coldplay', 'Placebo', 'Red Hot Chili Peppers', u'Bj\xf6rk', 
			'Beck', 'The Smashing Pumpkins', 'The White Stripes', 'Nirvana']
		"""
		if not self.name:
			raise AudioscrobblerError("tag name has to be set before calling this method")
		url = "http://ws.audioscrobbler.com/1.0/tag/%s/topartists.xml" % self.name
		xml = Webservice()._FetchUrl(url)
		data = Xml2Dict(ElementTree.XML(xml))
		
		self.count = int(data['@count'])
		artists = []
		if not 'artist' in data:
			return artists

		for artistData in data['artist']:
			artist = Artist(
				name = artistData['@name'],
				url = artistData['url'],
				thumbnail = artistData['thumbnail'],
				image = artistData['image'],
				streamable = artistData['@streamable'] == "yes"
			)
			if 'mbid' in artistData:
				artist.mbid = artistData['mbid']
			artist.count = int(artistData['@count'])
			artists.append(artist)
		return artists
	
	topArtists = property(GetTopArtists,
		doc = "Top artists for this tag")
	topArtist = property(lambda (self): len(self.GetTopArtists()) and self.GetTopArtists()[0] or None,
		doc = "Topmost artist for this tag")

	def GetTopAlbums(self):
		"""Get the top albums for this tag.

		Returns:
			An ordered list of Album objects corresponding to this tags's top albums.

		Usage:
			>>> tag = ws.GetTag('alternative')
			>>> albums = tag.GetTopAlbums()
			>>> [a.name for a in albums[:10]]
			['OK Computer', 'InTRO', 'Absolution', 'A Long And Ugly Road (European edition)', 'Nevermind', 
			'Kid A', 'In Rainbows', 'Black Holes And Revelations', 'Hapless', 'A Rush of Blood to the Head']
		"""
		if not self.name:
			raise AudioscrobblerError("tag name has to be set before calling this method")
		url = "http://ws.audioscrobbler.com/1.0/tag/%s/topalbums.xml" % self.name
		xml = Webservice()._FetchUrl(url)
		data = Xml2Dict(ElementTree.XML(xml))

		albums = []
		if not 'album' in data:
			return albums

		for albumData in data['album']:
			album = Album(
				artist = Artist(
					name = albumData['artist']['@name'],
					url = albumData['artist']['url']
				),
				name = albumData['@name'],
				url = albumData['url'],
				coverart = albumData['coverart']
			)

			if 'mbid' in albumData['artist']:
				album.artist.mbid = albumData['artist']['mbid']
				
			album.streamable = albumData['@streamable'] == "yes"
			album.count = int(albumData['@count'])
			albums.append(album)
		return albums

	topAlbums = property(GetTopAlbums,
		doc = "Top albums for this tag")
	topAlbum = property(lambda (self): len(self.GetTopAlbums()) and self.GetTopAlbums()[0] or None,
		doc = "Topmost album for this tag")

	def GetTopTracks(self):
		"""Get the top tracks for this tag.

		Returns:
			An ordered list of Track objects corresponding to this tags's top tracks.

		Usage:
			>>> tag = ws.GetTag('alternative')
			>>> tracks = tag.GetTopTracks()
			>>> [t.name for t in tracks[:10]]
			['Nude', 'Karma Police', 'Creep', "Don't Let Him Waste Your Time", 'Paranoid Android', 
			'Starlight', 'Fat Children', 'Clocks', 'Supermassive Black Hole', 'Time Is Running Out']
		"""
		if not self.name:
			raise AudioscrobblerError("tag name has to be set before calling this method")
		url = "http://ws.audioscrobbler.com/1.0/tag/%s/toptracks.xml" % self.name
		xml = Webservice()._FetchUrl(url)
		data = Xml2Dict(ElementTree.XML(xml))

		tracks = []
		if not 'track' in data:
			return tracks

		for trackData in data['track']:
			track = Track(
				artist = Artist(
					name = trackData['artist']['@name'],
					url = trackData['artist']['url']
				),
				name = trackData['@name'],
				url = trackData['url']
			)

			if 'mbid' in trackData['artist']:
				track.artist.mbid = trackData['artist']['mbid']

			track.count = int(trackData['@count'])
			track.streamable = trackData['@streamable'] == "yes"
			track.image = trackData['image']
			track.thumbnail = trackData['thumbnail']
			tracks.append(track)
		return tracks

	topTracks = property(GetTopTracks,
		doc = "Top tracks for this tag")
	topTrack = property(lambda (self): len(self.GetTopTracks()) and self.GetTopTracks()[0] or None,
		doc = "Topmost track for this tag")
	
	def AsDict(self):
		"""Return self as a dict."""
		return self.__dict__

	def __eq__(self, other):
		return self.name == other.name

	def __ne__(self, other):
		return not self.__eq__(other)

import cElementTree as ElementTree

from album import Album
from artist import Artist
from webservice import Webservice
from track import Track
from xml2dict import Xml2Dict
from error import AudioscrobblerError